/*
 *  Description: BOAT XU SOFT FHSS
 *  Version: V1.00
 *  Author: boat xu
 *  Email: xifengzui@outlook.com
 *  Date: 2020-07-10 15:48:21
 *  LastEditTime: 2020-07-22 15:32:29
 */ 

#include "bsf_types.h"
#include "bsf_itypes.h"
#include "bsf_rand.h"
#include "bsf_payload.h"
#include "bsf_debug.h"
bsf_paylaod_manager pm;

void bsf_payload_init()
{
    b_u8_t tt;

    for(tt=0; tt< TX_PAYLOAD_BUF_COUNT; tt++)
    {
        pm.info.tStatus[tt] = TPM_FREE;
    }
    
    for(tt=0; tt< RX_PAYLOAD_BUF_COUNT; tt++)
    {
        pm.info.rStatus[tt] = TPM_FREE;
    }
    
    pm.info.rRIndex = 0;
    pm.info.rWIndex = 0;
    pm.info.tRIndex = 0;
    pm.info.tWIndex = 0;

}

b_boolean bsf_payloadPushTXBuf_Begin(bsf_payload **outBuf)
{
    if(pm.info.tStatus[pm.info.tWIndex] == TPM_USED)
    {
        pm.info.txOverWriterLoss++;
        dprintf("        [ERROR][PAYLOAD]: TX BUFFER Full,Lost:%d.",pm.info.txOverWriterLoss);
        return b_false;
    }
    *outBuf = &(pm.TXPayload[pm.info.tWIndex]);
    //dprintf("        [INFO][PAYLOAD]: push TX[0x%x].",*outBuf);
    return b_true;
}

void bsf_payloadPushTXBuf_End(b_boolean isOkToPush)
{
    if(isOkToPush == b_false)
    {
        //dprintf("        [INFO][PAYLOAD]: TX push failed.");
        return;
    }
    pm.info.tStatus[pm.info.tWIndex] = TPM_USED;
    pm.info.tWIndex = (pm.info.tWIndex+1)%TX_PAYLOAD_BUF_COUNT;
}

b_boolean bsf_payloadPopTxBuf_Begin(bsf_payload **outBuf)
{
    if(pm.info.tStatus[pm.info.tRIndex] == TPM_FREE)
    {
        dprintf("        [ERROR][PAYLOAD]: TX BUFFER Empty.");
        return b_false;
    }
    *outBuf = &(pm.TXPayload[pm.info.tRIndex]);
    //dprintf("        [INFO][PAYLOAD]: pop TX[0x%x].",*outBuf);
    return b_true;
}

void bsf_payloadPopTxBuf_End(b_boolean isOkToPop)
{
    if(isOkToPop == b_false)
    {
        //dprintf("        [INFO][PAYLOAD]: TX Pop failed.");
        return;
    }
    pm.info.tStatus[pm.info.tRIndex] = TPM_FREE; 
    pm.info.tRIndex = (pm.info.tRIndex+1)%TX_PAYLOAD_BUF_COUNT;
}

b_boolean bsf_payloadPushRxBuf_Begin(bsf_payload **outBuf)
{
    if(pm.info.rStatus[pm.info.rWIndex] == TPM_USED)
    {
        pm.info.rxOverWriterLoss++;
        dprintf("        [ERROR][PAYLOAD]: RX BUFFER Full,Lost:%d.",pm.info.rxOverWriterLoss);
        return b_false;
    }
    *outBuf = &(pm.RXPayload[pm.info.rWIndex]);
    //dprintf("        [INFO][PAYLOAD]: push RX[0x%x].",*outBuf);
    return b_true;
}

void bsf_payloadPushRxBuf_End(b_boolean isOkToPush)
{
    if(isOkToPush == b_false)
    {
        //dprintf("        [INFO][PAYLOAD]: RX push failed.");
        return;
    }
    pm.info.rStatus[pm.info.rWIndex] = TPM_USED; 
    pm.info.rWIndex = (pm.info.rWIndex+1)%RX_PAYLOAD_BUF_COUNT;
}

b_boolean bsf_payloadPopRxBuf_Begin(bsf_payload **outBuf)
{
    if(pm.info.rStatus[pm.info.rRIndex] == TPM_FREE)
    {
        dprintf("        [ERROR][PAYLOAD]: try to read empty Buffer From RX BUFFER.");
        return b_false;
    }
    *outBuf = &(pm.TXPayload[pm.info.rRIndex]);
    //dprintf("        [INFO][PAYLOAD]: pop RX[0x%x].",*outBuf);
    return b_true;
}

void bsf_payloadPopRxBuf_End(b_boolean isOkToPop)
{
    if(isOkToPop == b_false)
    {
        dprintf("        [ERROR][PAYLOAD]: RX pop failed.");
        return;
    }
    pm.info.rStatus[pm.info.rRIndex] = TPM_FREE; 
    pm.info.rRIndex = (pm.info.rRIndex+1)%TX_PAYLOAD_BUF_COUNT;
}



b_boolean bsf_payloadInfoCheckIsOk(bsf_payload *inBuf)
{
    if((inBuf->stru.head.magicNumber[0] != MAGIC_NUM_1) || (inBuf->stru.head.magicNumber[1] != MAGIC_NUM_2))
    {
        dprintf("        [ERROR][PAYLOAD]:check magic number not match.");
        return b_false;
    }
    if(inBuf->stru.head.payloadType >= b_pt_max)
    {
        dprintf("        [ERROR][PAYLOAD]:check head no such type.");
        return b_false;
    }
    if(inBuf->stru.head.totalSize > BSF_PACKSIZE)
    {
        dprintf("        [ERROR][PAYLOAD]:check head length error.");
        return b_false;
    }
    return b_true;
}

void bsf_payloadInfoSet(payloadTypes payloadType,b_u8_t userDatasize,bsf_payload *inBuf)
{
    inBuf->stru.head.magicNumber[0] = MAGIC_NUM_1;
    inBuf->stru.head.magicNumber[1] = MAGIC_NUM_2;
    inBuf->stru.head.payloadType = payloadType;
    inBuf->stru.head.totalSize = sizeof(bsf_PayloadHead_Struct) + userDatasize;
}

b_boolean bsf_payloadInfoGet(payloadTypes *outTypes,b_u8_t *userDataSize,bsf_payload *inBuf)
{
    b_boolean ret = b_false;
    ret = bsf_payloadInfoCheckIsOk(inBuf);
    
    if(ret == b_false)
    {
        return b_false;
    }

    *outTypes = inBuf->stru.head.payloadType;
    *userDataSize = inBuf->stru.head.totalSize - sizeof(bsf_PayloadHead_Struct);
}